#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@file: box_tag.py
@time: 2024-06-25 11:28
@desc:
"""
import traceback
from io import BytesIO
from urllib.parse import urlencode

from flask import Blueprint, request, jsonify, send_file
import pandas as pd

from common_tools import apply_formatting
from global_scope import MAX_PAGE_SIZE, get_db, box_tags_sheet_name, images_sheet_name
from project_model import BoxTag, Image
from tools import get_box_tags_df, excel_to_box_tags, get_images_df
from tools import log_operations, token_required

db = get_db()
box_tag_bp = Blueprint('box_tag', __name__, url_prefix='/box_tags')


@box_tag_bp.route('', methods=['POST'])
@log_operations
@token_required
def add_box_tag():
    data = request.json
    tagName = data.get('tagName')
    image_ids = data.get('image_ids', [])

    if not tagName:
        return jsonify({"code": 1, "message": "tagName is required"}), 400

    box_tag = BoxTag.query.filter_by(tagName=tagName).first()
    if not box_tag:
        remark = data.get('remark', "")

        box_tag = BoxTag(tag_name=tagName, remark=remark)
        db.session.add(box_tag)
        db.session.commit()

    if image_ids:
        images = Image.query.filter(Image.id.in_(image_ids)).all()
        box_tag.images.extend(images)
        db.session.commit()

    return jsonify({"code": 0, "message": "BoxTag added successfully", "data": box_tag.id}), 201


@box_tag_bp.route('/<int:box_tag_id>', methods=['PATCH'])
@log_operations
@token_required
def update_box_tag(box_tag_id):
    data = request.json
    box_tag = BoxTag.query.get(box_tag_id)
    if not box_tag:
        return jsonify({"code": 1, "message": "BoxTag not found"}), 404

    if 'tagName' in data:
        box_tag.tagName = data['tagName']

    if 'remark' in data:
        box_tag.remark = data['remark']

    if 'images' in data:
        image_ids = [c.get('id') for c in data['images'] if c.get('id')]
        images = Image.query.filter(Image.id.in_(image_ids)).all()
        box_tag.images = images

    db.session.commit()

    return jsonify({"code": 0, "message": "BoxTag updated successfully"}), 200


@box_tag_bp.route('/<int:box_tag_id>', methods=['DELETE'])
@log_operations
@token_required
def delete_box_tag(box_tag_id):
    box_tag = BoxTag.query.get(box_tag_id)
    if not box_tag:
        return jsonify({"code": 1, "message": "BoxTag not found"}), 404

    db.session.delete(box_tag)
    db.session.commit()

    return jsonify({"code": 0, "message": "BoxTag deleted successfully"}), 200


@box_tag_bp.route('', methods=['GET'])
@log_operations
@token_required
def get_box_tags():
    tag_name = request.args.get('tagName', None)
    page_no = int(request.args.get('pageNo', 1))
    page_size = int(request.args.get('pageSize', MAX_PAGE_SIZE))

    if tag_name:
        box_tags_query = BoxTag.query.filter(BoxTag.tagName.like(f'%{tag_name}%'))
    else:
        box_tags_query = BoxTag.query

    # 使用paginate方法进行分页
    pagination = box_tags_query.paginate(page=page_no, per_page=page_size, error_out=False)
    box_tags = pagination.items

    # 准备响应数据
    data = {
        "pageData": [
            {
                "id": bt.id,
                "tagName": bt.tagName,
                "remark": bt.remark,
                "createTime": bt.createTime.isoformat(),
                "updateTime": bt.updateTime.isoformat(),
                "images": [{"id": img.id, "imageUrl": img.imageUrl} for img in bt.images]
            } for bt in box_tags
        ],
        "total": pagination.total
    }

    # 构造原始URL，包括分页和其他查询参数
    encoded_query_params = urlencode(request.args)
    origin_url = f"{request.base_url}?{encoded_query_params}"

    return jsonify({
        "code": 0,
        "message": "OK",
        "data": data,
        "originUrl": origin_url
    }), 200


@box_tag_bp.route('/upload', methods=['POST'])
@log_operations
@token_required
def upload_box_tags():
    if 'file' not in request.files:
        return jsonify({"code": 1, "message": "No file part"}), 400

    file = request.files['file']
    if file.filename == '':
        return jsonify({"code": 1, "message": "No selected file"}), 400

    try:
        new_tags, updated_tags = excel_to_box_tags(file, request)
        return jsonify({
            "code": 0,
            "message": f"Contacts uploaded successfully: {new_tags} added, {updated_tags} updated"
        }), 201
    except Exception as e:
        tb = traceback.format_exc()
        request.trace_logger.error(f"Exception occurred: {str(e)}\n{tb}")
        return jsonify({"code": 1, "message": str(e)}), 500


@box_tag_bp.route('/download', methods=['GET'])
@log_operations
@token_required
def download_box_tags():
    output = BytesIO()
    with pd.ExcelWriter(output, engine='openpyxl') as writer:
        df_objs = [
            (get_images_df(), images_sheet_name),
            (get_box_tags_df(), box_tags_sheet_name),
        ]
        # 写入数据
        for df, sheet_name in df_objs:
            df.to_excel(writer, index=False, sheet_name=sheet_name)
            apply_formatting(writer.sheets[sheet_name], df)
    output.seek(0)

    return send_file(output, download_name="BoxTags.xlsx", as_attachment=True)
